#include "gui.h"
#include "serial_port.h"
#include <QVBoxLayout>
#include <QHBoxLayout>
#include <QGroupBox>
#include <QSerialPortInfo>
#include <QDateTime>
#include <QIntValidator>
#include <QRegularExpression>
#include <QDebug> 
#include "serv_datapack.h"

MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) {
    serialPort = new SerialPort(this);
    serialDataTimer = new QTimer(this);
    serialDataTimer->setInterval(5);

    setupUI();
    setupConnections();

    setFixedSize(800, 300);
    setWindowTitle("Serial Port Tool");
}

MainWindow::~MainWindow() {
    if (serialPort->isOpen()) {
        serialPort->close();
    }
}

void MainWindow::setupUI() {
    QWidget *centralWidget = new QWidget(this);
    setCentralWidget(centralWidget);

    // Main layouts
    QHBoxLayout *mainLayout  = new QHBoxLayout(centralWidget);
    QVBoxLayout *leftLayout  = new QVBoxLayout();
    QVBoxLayout *rightLayout = new QVBoxLayout();

    // Port settings group
    QGroupBox *portGroup = new QGroupBox("Port Settings");
    QHBoxLayout *portLayout = new QHBoxLayout(portGroup);
    
    portComboBox = new QComboBox();
    foreach (const QSerialPortInfo &info, QSerialPortInfo::availablePorts()) {
        portComboBox->addItem(info.portName());
    }
    
    baudrateComboBox = new QComboBox();
    baudrateComboBox->addItems({"9600", "19200", "38400", "57600", "115200", "400000"});
    baudrateComboBox->setCurrentText("400000");
    
    openPortButton = new QPushButton("Open Port");
    
    portLayout->addWidget(portComboBox);
    portLayout->addWidget(baudrateComboBox);
    portLayout->addWidget(openPortButton);

    // Progress control group
    QGroupBox *progressGroup = new QGroupBox("Progress Control");
    QHBoxLayout *progressLayout = new QHBoxLayout(progressGroup);
    
    progressBar = new QProgressBar();
    progressBar->setRange(0, 65535);
    progressBar->setValue(32768);
    
    progressValueEdit = new QLineEdit("32768");
    progressValueEdit->setValidator(new QIntValidator(0, 65535, this));
    progressValueEdit->setMaximumWidth(80);
    
    progressLayout->addWidget(progressBar);
    progressLayout->addWidget(progressValueEdit);

    // Screen control buttons
    QGroupBox *screenGroup = new QGroupBox("Screen Control");
    QHBoxLayout *screenLayout = new QHBoxLayout(screenGroup);
    
    //fullScreenButton = new QPushButton("Full Screen");
    leftScreenButton = new QPushButton("Left Screen on");
    rightScreenButton = new QPushButton("Right Screen on");
    
    //screenLayout->addWidget(fullScreenButton);
    screenLayout->addWidget(leftScreenButton);
    screenLayout->addWidget(rightScreenButton);

    // Settings button
    settingsButton = new QPushButton("Settings");

    // Slider
    valueSlider = new QSlider(Qt::Vertical);
    valueSlider->setRange(0, 65535);
    valueSlider->setValue(32768);

    // Send data group
    QGroupBox *sendGroup = new QGroupBox("Send Data");
    QHBoxLayout *sendLayout = new QHBoxLayout(sendGroup);
    
    sendDataEdit = new QLineEdit();
    sendDataEdit->setPlaceholderText("Enter hex data (e.g. 0x79 0xAA 0xBB)");
    
    sendButton = new QPushButton("Send");
    
    sendLayout->addWidget(sendDataEdit);
    sendLayout->addWidget(sendButton);

    // Receive data group
    QGroupBox *receiveGroup = new QGroupBox("Received Data");
    QVBoxLayout *receiveLayout = new QVBoxLayout(receiveGroup);
    
    receiveTextEdit = new QTextEdit();
    receiveTextEdit->setReadOnly(true);
    
    receiveLayout->addWidget(receiveTextEdit);

    // Assemble left layout
    leftLayout->addWidget(portGroup);
    leftLayout->addWidget(progressGroup);
    leftLayout->addWidget(screenGroup);
    leftLayout->addWidget(settingsButton);
    leftLayout->addStretch();

    // Assemble right layout
    rightLayout->addWidget(receiveGroup);
    rightLayout->addWidget(valueSlider);
    rightLayout->addWidget(sendGroup);

    // Add to main layout
    mainLayout->addLayout(leftLayout);
    mainLayout->addWidget(valueSlider);
    mainLayout->addLayout(rightLayout);
}

void MainWindow::setupConnections() {
    connect(openPortButton, &QPushButton::clicked, this, &MainWindow::onOpenPortClicked);
    connect(sendButton, &QPushButton::clicked, this, &MainWindow::onSendDataClicked);
    //connect(fullScreenButton, &QPushButton::clicked, this, &MainWindow::onFullScreenClicked);
    connect(leftScreenButton, &QPushButton::clicked, this, &MainWindow::onLeftScreenClicked);
    connect(rightScreenButton, &QPushButton::clicked, this, &MainWindow::onRightScreenClicked);
    connect(settingsButton, &QPushButton::clicked, this, &MainWindow::onSettingsClicked);
    connect(valueSlider, &QSlider::valueChanged, this, &MainWindow::onSliderValueChanged);
    connect(progressValueEdit, &QLineEdit::editingFinished, this, &MainWindow::onProgressValueChanged);
    connect(serialPort, &SerialPort::dataReceived, this, &MainWindow::handleSerialData);
    connect(serialDataTimer, &QTimer::timeout, this, &MainWindow::processSerialData);
}

void MainWindow::onOpenPortClicked() {
    if (serialPort->isOpen()) {
        serialPort->close();
        openPortButton->setText("Open Port");
        return;
    }
    QString portName = "/dev/"+ portComboBox->currentText();
    int baudrate = baudrateComboBox->currentText().toInt();
    
    if (serialPort->open(portName, baudrate)) {
        openPortButton->setText("Close Port");
        serialDataTimer->start();
    }
}

void MainWindow::onSettingsClicked(){
    if (!serialPort->isOpen()) return;

    QByteArray data;
    data.append(0x79);
    data.append(0x6C);
    data.append(static_cast<unsigned char>(0x00));
    data.append(static_cast<unsigned char>(0x00));
    data.append(0x0B);

    QByteArray payload;
    payload.append(0x02);
    payload.append(static_cast<unsigned char>(0x00));
    payload.append(0x02);
    payload.append(0x83);
    
    if((leftScreenState == 1)&&(rightScreenState == 1))
    {
        BacklightSwitch = 0x01;
    }
    else if(rightScreenState == 1)
    {
        BacklightSwitch = 0x03;
    }
    else if(leftScreenState == 1)
    {
        BacklightSwitch = 0x04;
    }
    else 
    {
        BacklightSwitch = 0x02;
    }

    payload.append(BacklightSwitch);
    payload.append((uint8_t)(BacklightValue>>8));
    payload.append((uint8_t)BacklightValue);

    uint32_t crc = CRC32_Check_Code(
        const_cast<uint8_t*>(reinterpret_cast<const uint8_t*>(payload.constData())),
        payload.size()
    );

    //data.append(static_cast<char>(payload.size() + 4));

    data.append(payload);
    data.append(static_cast<char>((crc >> 24) & 0xFF));
    data.append(static_cast<char>((crc >> 16) & 0xFF));
    data.append(static_cast<char>((crc >> 8 ) & 0xFF));
    data.append(static_cast<char>((crc )      & 0xFF));

    serialPort->write(data);
}

void MainWindow::onSendDataClicked() {
    if (!serialPort->isOpen()) return;

    QString text = sendDataEdit->text();
    text.remove(' ');
    
    if (text.isEmpty()) return;
    
    QByteArray data;
    bool ok;
    
    for (int i = 0; i < text.length(); i += 2) {
        QString byteStr = text.mid(i, 2);
        uint8_t byte = byteStr.toUInt(&ok, 16);
        if (ok) {
            data.append(byte);
        }
    }
    
    if (!data.isEmpty()) {
        serialPort->write(data);
    }
}

void MainWindow::onFullScreenClicked() {
    // Customize this function as needed
    qDebug() << "Full Screen button clicked";
}

void MainWindow::onLeftScreenClicked() {
    // Customize this function as needed
    if(leftScreenState == 1)
    {
        leftScreenButton->setText("Left Screen off");
        leftScreenState = 0;
    }
    else
    {
        leftScreenButton->setText("Left Screen on");
        leftScreenState = 1;
    }
    qDebug() << "Left Screen button clicked";
}

void MainWindow::onRightScreenClicked() {
    // Customize this function as needed
    if(rightScreenState == 1)
    {
        rightScreenButton->setText("Right Screen off");
        rightScreenState = 0;
    }
    else
    {
        rightScreenButton->setText("Right Screen on");
        rightScreenState = 1;
    }
    qDebug() << "Right Screen button clicked";
}

void MainWindow::onSliderValueChanged(int value) {
    progressBar->setValue(value);
    progressValueEdit->setText(QString::number(value));
    BacklightValue = value;
}

void MainWindow::onProgressValueChanged() {
    bool ok;
    int value = progressValueEdit->text().toInt(&ok);
    if (ok && value >= 0 && value <= 65535) {
        progressBar->setValue(value);
        valueSlider->setValue(value);
        BacklightValue = value;
    }
}

void MainWindow::handleSerialData(const QByteArray &data) {
    // Data will be processed in processSerialData with 5ms timer
    // This is just for buffering the data
}

void MainWindow::processSerialData() {
    // QByteArray data = serialPort->readAll();
    // if (data.isEmpty()) return;

    // QString timestamp = QDateTime::currentDateTime().toString("hh:mm:ss.zzz");
    // QString hexData = data.toHex(' ').toUpper();
    
    // receiveTextEdit->append(QString("[%1] %2").arg(timestamp, hexData));
    serialPort->HandleData();
}

